/*
 * This file is part of ELCube.
 *
 * ELCube is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * ELCube is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with ELCube.  If not, see <https://www.gnu.org/licenses/>.
 */
package cn.nkpro.elcube.docengine.cards;

import cn.nkpro.elcube.annotation.NkNote;
import cn.nkpro.elcube.basic.NkProperties;
import cn.nkpro.elcube.co.NkCustomObjectManager;
import cn.nkpro.elcube.co.easy.EasySingle;
import cn.nkpro.elcube.docengine.NkUpLoadField;
import cn.nkpro.elcube.docengine.NkField;
import cn.nkpro.elcube.docengine.model.DocDefIV;
import cn.nkpro.elcube.docengine.model.DocHV;
import cn.nkpro.elcube.docengine.utils.ZipUtils;
import cn.nkpro.elcube.exception.NkSystemException;
import cn.nkpro.elcube.utils.UUIDHexGenerator;
import org.apache.tools.zip.ZipOutputStream;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.*;

@Order(1001)
@NkNote("表单")
@Component("NkDynamicForm")
public class NkDynamicForm extends NkDynamicBase<Map<String,Object>, NkDynamicFormDef> {

    @Autowired
    private NkCustomObjectManager nkCustomObjectManager;

    @Override
    public boolean supports(String classify) {
        return true;
    }

    @Override
    public String getDataComponentName() {
        return "NkDynamicForm";
    }

    @Override
    protected String[] getDefComponentNames() {
        return new String[]{"NkDynamicFormDef"};
    }

    @Autowired
    private NkProperties properties;

    private Format format = new SimpleDateFormat(String.format("yyyyMMdd%sHHmmss", File.separator));

    @Override
    public Map<String,Object> afterCreate(DocHV doc, DocHV preDoc, Map<String,Object> data, DocDefIV defIV, NkDynamicFormDef d) {
        this.copyFromPre(preDoc, data, defIV, d.getItems());
        EasySingle single = EasySingle.from(data);
        // 处理数据
        this.execSpEL(single, doc, d.getItems(), defIV.getCardKey(), false, null, preDoc, true);
        if(doc.isViewed()){
            // 处理编辑时需要的选项
            this.processOptions(single, doc, d.getItems());
            // 处理显示
            this.processControl(single,doc,d.getItems(),defIV.getCardKey());
        }
        return super.afterCreate(doc, preDoc, data, defIV, d);
    }

    @Override
    public Map<String,Object> afterGetData(DocHV doc, Map<String,Object> data, DocDefIV defIV, NkDynamicFormDef d) {
        if(doc.isViewed()) {
            EasySingle single = EasySingle.from(data);
            this.processOptions(single, doc, d.getItems());
            this.processControl(single, doc, d.getItems(), defIV.getCardKey());
        }
        return super.afterGetData(doc, data, defIV, d);
    }

    @Override
    public Map<String, Object> beforeUpdate(DocHV doc, Map<String, Object> data, Map<String, Object> original, DocDefIV defIV, NkDynamicFormDef d) {
        this.processUpdate(EasySingle.from(data),doc,d.getItems(), defIV.getCardKey());
        return super.beforeUpdate(doc, data, original, defIV, d);
    }

    @Override
    public Map<String, Object> afterUpdated(DocHV doc, Map<String, Object> data, Map<String, Object> original, DocDefIV defIV, NkDynamicFormDef d) {
        if(doc.isViewed()) {
            EasySingle single = EasySingle.from(data);
            this.processOptions(single, doc, d.getItems());
            this.processControl(single, doc, d.getItems(), defIV.getCardKey());
        }
        return super.afterUpdated(doc, data, original, defIV, d);
    }

    @Override
    public Map<String,Object> calculate(DocHV doc, Map<String,Object> data, DocDefIV defIV, NkDynamicFormDef d, boolean isTrigger, Object options) {
        EasySingle single = EasySingle.from(data);
        this.execSpEL(single, doc, d.getItems(), defIV.getCardKey(), isTrigger, (Map) options);
        if(doc.isViewed()) {
            this.processOptions(single, doc, d.getItems());
            this.processControl(single, doc, d.getItems(), defIV.getCardKey());
        }
        return super.calculate(doc, data, defIV, d, isTrigger, options);
    }

    @Override
    public Object call(DocHV doc, Map<String, Object> data, DocDefIV defIV, NkDynamicFormDef d, Object options) {
        List<NkDynamicFormDefI> items = d.getItems();
        EasySingle card = EasySingle.from(data);
        List<String> filesPath = new ArrayList<>();
        items.forEach(item ->{
            String inputType = item.getInputType();
            if(!"-".equals(inputType)){
                NkField nkField = nkCustomObjectManager.getCustomObject(inputType, NkField.class);
                if(nkField instanceof NkUpLoadField){
                    List<String> paths = ((NkUpLoadField) nkField).getFilesPath(item, card);
                    filesPath.addAll(paths);
                }
            }
        });


        String wordFileName = defIV.getCardName();
        String wordUrl = String.join(File.separator, "tmp", format.format(new Date()), UUIDHexGenerator.generate()) + "\\" + wordFileName +".zip";

        String wordUrlNew = wordUrl.replace("\\", "/");
        String pdfZipUrl = String.join(File.separator, properties.getFileRootPath(), wordUrlNew).replace("\\", "/");
        FileOutputStream fos = null;
        ZipOutputStream zipOut = null;
        File fileZip = new File(pdfZipUrl);
        boolean mkdirs = fileZip.getParentFile().mkdirs();
        if(mkdirs){
            try{
                //创建文件输出流
                fos = new FileOutputStream(fileZip);
                zipOut = new ZipOutputStream(fos);
                zipOut.setEncoding("UTF-8");//设置压缩包中文件名的字符集
                for (String s : filesPath) {
                    String pathR = String.join(File.separator, properties.getFileRootPath(), s).replaceAll("\\\\", "/");
                    File f = new File(pathR);  //根据文件路径创建文件
                    ZipUtils.zipFile(f, zipOut);  //将每一个文件写入zip文件包内，即进行打包
                }
                zipOut.close();
                fos.close();
                return wordUrlNew;
            }catch (Exception e){
                try {
                    if (null != zipOut) {
                        zipOut.flush();
                        zipOut.close();
                    }
                    if (null != fos) {
                        fos.flush();
                        fos.close();
                    }
                } catch (IOException ex) {
                    log.error(ex.getMessage(),ex);
                }
                log.error(e.getMessage(),e);
            }
        }else {
            throw new NkSystemException("文件夹创建失败！");
        }

        return wordUrlNew;
    }

    @Override
    public Object callDef(NkDynamicFormDef def, Object options) {
        return customObjectManager.getCustomObjectDescriptionList(NkField.class, false, (entry)-> entry.getValue() instanceof NkDynamicFormField);
    }

}
